home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / sgml / msdos / sgml07 / lineout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-27  |  12.8 KB  |  611 lines

  1. /* lineout.c -
  2.    Implements line-oriented output format.
  3.  
  4.      Written by James Clark (jjc@jclark.com).
  5. */
  6.  
  7. #include "config.h"
  8. #include "std.h"
  9. #include "entity.h"           /* Templates for entity control blocks. */
  10. #include "adl.h"              /* Definitions for attribute list processing. */
  11. #include "sgmlmain.h"         /* Main interface to SGML services. */
  12. #include "lineout.h"
  13. #include "appl.h"
  14.  
  15. static VOID flush_data P((void));
  16. static VOID define_external_entity P((PNE));
  17. static VOID define_entity P((UNCH *));
  18. static VOID handle_attributes P((UNCH *, struct ad *));
  19. static VOID handle_token_list P((UNCH *, struct ad *, int));
  20. static VOID handle_single_token P((UNCH *, struct ad *, int));
  21. static VOID output_notation P((UNCH *, UNIV));
  22. static VOID output_internal_entity P((UNCH *, int, UNCH *));
  23. static VOID output_external_entity P((UNCH *, int, UNIV, UNCH *));
  24. static VOID output_subdoc P((UNCH *, UNIV));
  25. #ifdef SUPPORT_SUBDOC
  26. static VOID process_subdoc P((UNCH *, UNIV));
  27. #endif /* SUPPORT_SUBDOC */
  28. static VOID output_record_end P((void));
  29. static VOID output_pcdata P((UNS, UNCH *));
  30. static VOID output_cdata P((UNS, UNCH *));
  31. static VOID output_sdata P((UNS, UNCH *));
  32. static VOID output_entity_reference P((UNCH *));
  33. static VOID output_start_tag P((UNCH *));
  34. static VOID output_end_tag P((UNCH *));
  35. static VOID output_processing_instruction P((UNS, UNCH *));
  36. static VOID output_implied_attribute P((UNCH *, UNCH *));
  37. static char *attribute_type_string P((int));
  38. static VOID output_begin_attribute P((UNCH *, UNCH *, int));
  39. static VOID output_attribute_token P((UNS, UNCH *));
  40. static VOID output_end_attribute P((void));
  41. static VOID print_data P((UNS, UNCH *, int));
  42. static VOID print_string P((UNS, UNCH *, int));
  43. static VOID print_id P((UNIV));
  44. static VOID print_filename P((char *));
  45. static VOID output_location P((void));
  46.  
  47. static int have_data = 0;
  48. static char *current_filename = 0;
  49. static unsigned long current_lineno = 0;
  50.  
  51. VOID process_document()
  52. {
  53.      enum sgmlevent rc;
  54.      struct rcbtag rcbtag;
  55.      struct rcbdata rcbdaf;
  56.  
  57.      while ((rc = sgmlnext(&rcbdaf, &rcbtag)) != SGMLEOD) {
  58. #ifdef SUPPORT_SUBDOC
  59.       if (rc == SGMLDAF && !CONTERSW(rcbdaf) && NDESW(rcbdaf)
  60.           && NEXTYPE(NEPTR(rcbdaf)) == ESNSUB) {
  61.            process_subdoc(NEENAME(NEPTR(rcbdaf)) + 1,
  62.                   NEID(NEPTR(rcbdaf)));
  63.            continue;
  64.       }
  65. #endif /* SUPPORT_SUBDOC */
  66.       if (!suppsw)
  67.            switch (rc) {
  68.            case SGMLDAF:
  69.             if (CONTERSW(rcbdaf))
  70.              break;
  71.             if (CDESW(rcbdaf))
  72.              output_cdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  73.             else if (SDESW(rcbdaf))
  74.              output_sdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  75.             else if (NDESW(rcbdaf)) {
  76.              assert(NEXTYPE(NEPTR(rcbdaf)) != ESNSUB);
  77.              if (!sgmlment(NEENAME(NEPTR(rcbdaf))))
  78.                   define_external_entity(NEPTR(rcbdaf));
  79.              output_entity_reference(NEENAME(NEPTR(rcbdaf)) + 1);
  80.             }
  81.             else
  82.              output_pcdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  83.             break;
  84.            case SGMLSTG:
  85.             if (CONTERSW(rcbtag))
  86.              break;
  87.             if (ALPTR(rcbtag))
  88.              handle_attributes((UNCH *)NULL, ALPTR(rcbtag));
  89.             output_start_tag(CURGI(rcbtag));
  90.             break;
  91.            case SGMLETG:
  92.             if (CONTERSW(rcbtag))
  93.              break;
  94.             output_end_tag(CURGI(rcbtag));
  95.             break;
  96.            case SGMLPIS:
  97.             if (CONTERSW(rcbdaf))
  98.              break;
  99.             output_processing_instruction(PDATALEN(rcbdaf),
  100.                           PDATA(rcbdaf));
  101.             break;
  102.            case SGMLREF:
  103.             if (CONTERSW(rcbdaf))
  104.              break;
  105.             output_record_end();
  106.             break;
  107.            default:
  108.             abort();
  109.            }
  110.      }
  111. }
  112.  
  113. static VOID define_external_entity(p)
  114. PNE p;
  115. {
  116.      if (NEXTYPE(p) == ESNSUB)
  117.       output_subdoc(NEENAME(p) + 1, NEID(p));
  118.      else {
  119.       if (!NEDCNMARK(p))
  120.            output_notation(NEDCN(p) + 1, NEDCNID(p));
  121.       output_external_entity(NEENAME(p) + 1, NEXTYPE(p), NEID(p),
  122.                  NEDCN(p) + 1);
  123.       if (NEAL(p))
  124.            handle_attributes(NEENAME(p) + 1, NEAL(p));
  125.      }
  126. }
  127.  
  128. static VOID define_entity(ename)
  129. UNCH *ename;
  130. {
  131.      int rc;
  132.      PNE np;
  133.      UNCH *tp;
  134.      
  135.      if (sgmlment(ename))        /* already defined it */
  136.       return;
  137.      rc = sgmlgent(ename, &np, &tp);
  138.      switch (rc) {
  139.      case 1:
  140.       define_external_entity(np);
  141.       break;
  142.      case 2:
  143.      case 3:
  144.       output_internal_entity(ename + 1, rc == 3, tp);
  145.       break;
  146.      }
  147. }
  148.  
  149. /* ENT is the name of the entity with which these attributes are associated;
  150. if it's NULL, they're associated with the next start tag. */
  151.  
  152. static VOID handle_attributes(ent, al)
  153. UNCH *ent;
  154. struct ad *al;
  155. {
  156.      int aln;
  157.  
  158.      for (aln = 1; aln <= ADN(al); aln++) {
  159.       if (GET(ADFLAGS(al, aln), AERROR))
  160.            ;
  161.       else if (GET(ADFLAGS(al, aln), AINVALID))
  162.            ;
  163.       else if (ADVAL(al, aln) == NULL)
  164.            output_implied_attribute(ent, ADNAME(al, aln));
  165.       else if (ADTYPE(al, aln) >= ATKNLIST)
  166.            handle_token_list(ent, al, aln);
  167.       else
  168.            handle_single_token(ent, al, aln);
  169.       if (BITON(ADFLAGS(al, aln), AGROUP))
  170.            aln += ADNUM(al, aln);
  171.      }
  172. }
  173.  
  174. static VOID handle_token_list(ent, al, aln)
  175. UNCH *ent;
  176. struct ad *al;
  177. int aln;
  178. {
  179.      UNCH *ptr;
  180.      int i;
  181.      if (ADTYPE(al, aln) == AENTITYS) {
  182.       ptr = ADVAL(al, aln);
  183.       for (i = 0; i < ADNUM(al, aln); i++) {
  184.            /* Temporarily make token look like normal
  185.           name with length and EOS. */
  186.            UNCH c = ptr[*ptr + 1];
  187.            ptr[*ptr + 1] = '\0';
  188.            *ptr += 2;
  189.            define_entity(ptr);
  190.            *ptr -= 2;
  191.            ptr += *ptr + 1;
  192.            *ptr = c;
  193.       }
  194.      }
  195.      output_begin_attribute(ent, ADNAME(al, aln), ADTYPE(al, aln));
  196.      ptr = ADVAL(al, aln);
  197.      for (i = 0; i < ADNUM(al, aln); i++) {
  198.       /* The first byte is a length NOT including the length
  199.          byte; the tokens are not EOS terminated. */
  200.       output_attribute_token(*ptr, ptr + 1);
  201.       ptr += *ptr + 1;
  202.      }
  203.      output_end_attribute();
  204. }
  205.  
  206. static VOID handle_single_token(ent, al, aln)
  207. UNCH *ent;
  208. struct ad *al;
  209. int aln;
  210. {
  211.      if (ADTYPE(al, aln) == ANOTEGRP && !DCNMARK(ADDATA(al, aln).x))
  212.       output_notation(ADVAL(al, aln) + 1,
  213.               ADDATA(al, aln).x->dcnid);
  214.      else if (ADTYPE(al, aln) == AENTITY)
  215.       define_entity(ADVAL(al, aln));
  216.      output_begin_attribute(ent, ADNAME(al, aln), ADTYPE(al, aln));
  217.      if (ADTYPE(al, aln) == ACHARS)
  218.       output_attribute_token(ustrlen(ADVAL(al, aln)), ADVAL(al, aln));
  219.      else
  220.       output_attribute_token(*ADVAL(al, aln) - 2, ADVAL(al, aln) + 1);
  221.      output_end_attribute();
  222. }
  223.  
  224. static VOID output_notation(name, id)
  225. UNCH *name;
  226. UNIV id;
  227. {
  228.      flush_data();
  229.      printf("%c%s ", DEFINE_NOTATION_CODE, name);
  230.      print_id(id);
  231.      putchar('\n');
  232. }
  233.  
  234. static VOID output_internal_entity(ename, is_sdata, text)
  235. UNCH *ename;
  236. int is_sdata;
  237. UNCH *text;
  238. {
  239.      flush_data();
  240.      printf("%c%s %s ", DEFINE_INTERNAL_ENTITY_CODE, ename,
  241.         is_sdata ? "SDATA" : "CDATA");
  242.      print_string(text ? ustrlen(text) : 0, text, 0);
  243.      putchar('\n');
  244. }
  245.  
  246. static VOID output_subdoc(nm, id)
  247. UNCH *nm;
  248. UNIV id;
  249. {
  250.      flush_data();
  251.      printf("%c%s ", DEFINE_SUBDOC_ENTITY_CODE, nm);
  252.      print_id(id);
  253.      putchar('\n');
  254. }
  255.  
  256. #ifdef SUPPORT_SUBDOC
  257.  
  258. static VOID process_subdoc(nm, id)
  259. UNCH *nm;
  260. UNIV id;
  261. {
  262.      char **argv;
  263.      int ret;
  264.  
  265.      if (!suppsw) {
  266.       flush_data();
  267.       output_location();
  268.       printf("%c%s\n", START_SUBDOC_CODE, nm);
  269.       fflush(stdout);
  270.      }
  271.      fflush(stderr);
  272.  
  273.      argv = make_argv(id);
  274.      ret = run_process(argv);
  275.      if (ret != 0)
  276.       suberr++;
  277.  
  278.      if (!suppsw)
  279.       printf("%c%s\n", END_SUBDOC_CODE, nm);
  280.      current_filename = 0;
  281.      free(argv);
  282.      get_subcaps();
  283. }
  284.  
  285. #endif /* SUPPORT_SUBDOC */
  286.  
  287. static VOID output_external_entity(nm, xtype, id, dcn)
  288. UNCH *nm, *dcn;
  289. UNIV id;
  290. int xtype;
  291. {
  292.      char *type;
  293.  
  294.      flush_data();
  295.      switch (xtype) {
  296.      case ESNCDATA:
  297.       type = "CDATA";
  298.       break;
  299.      case ESNNDATA:
  300.       type = "NDATA";
  301.       break;
  302.      case ESNSDATA:
  303.       type = "SDATA";
  304.       break;
  305.      default:
  306.       return;
  307.      }
  308.      printf("%c%s %s %s ", DEFINE_EXTERNAL_ENTITY_CODE, nm, type, dcn);
  309.      print_id(id);
  310.      putchar('\n');
  311. }
  312.  
  313. static VOID output_record_end()
  314. {
  315.      static UNCH re = RECHAR;
  316.      print_data(1, &re, 0);
  317. }
  318.  
  319. static VOID output_pcdata(n, s)
  320. UNS n;
  321. UNCH *s;
  322. {
  323.      print_data(n, s, 0);
  324. }
  325.  
  326. static VOID output_cdata(n, s)
  327. UNS n;
  328. UNCH *s;
  329. {
  330.      print_data(n, s, 0);
  331. }
  332.  
  333. static VOID output_sdata(n, s)
  334. UNS n;
  335. UNCH *s;
  336. {
  337.      print_data(n, s, 1);
  338. }
  339.  
  340. static VOID output_entity_reference(s)
  341. UNCH *s;
  342. {
  343.      flush_data();
  344.      output_location();
  345.      printf("%c%s\n", REFERENCE_ENTITY_CODE, s);
  346. }
  347.  
  348. static VOID output_start_tag(s)
  349. UNCH *s;
  350. {
  351.      flush_data();
  352.      output_location();
  353.      printf("%c%s\n", START_CODE, s);
  354. }
  355.  
  356. static VOID output_end_tag(s)
  357. UNCH *s;
  358. {
  359.      flush_data();
  360.      printf("%c%s\n", END_CODE, s);
  361. }
  362.  
  363. static VOID output_processing_instruction(n, s)
  364. UNS n;
  365. UNCH *s;
  366. {
  367.      flush_data();
  368.      output_location();
  369.      putchar(PI_CODE);
  370.      print_string(n, s, 0);
  371.      putchar('\n');
  372. }
  373.  
  374. static VOID output_implied_attribute(ent, aname)
  375. UNCH *ent, *aname;
  376. {
  377.      flush_data();
  378.      if (ent)
  379.       printf("%c%s %s IMPLIED\n", DATA_ATTRIBUTE_CODE, ent, aname);
  380.      else
  381.       printf("%c%s IMPLIED\n", ATTRIBUTE_CODE, aname);
  382. }
  383.  
  384. static char *attribute_type_string(type)
  385. int type;
  386. {
  387.      switch (type) {
  388.      case ANMTGRP:
  389.      case ANAME:
  390.      case ANMTOKE:
  391.      case ANUTOKE:
  392.      case ANUMBER:
  393.      case ANAMES:
  394.      case ANMTOKES:
  395.      case ANUTOKES:
  396.      case ANUMBERS:
  397.       return "TOKEN";
  398.      case ANOTEGRP:
  399.       return "NOTATION";
  400.      case ACHARS:
  401.       return "CDATA";
  402.      case AENTITY:
  403.      case AENTITYS:
  404.       return "ENTITY";
  405.      case AID:
  406.       return "ID";
  407.      case AIDREF:
  408.      case AIDREFS:
  409.       return "IDREF";
  410.      }
  411. #if 0
  412.      fatal("invalid attribute type %d", type);
  413. #endif
  414.      return "INVALID";
  415. }      
  416.  
  417. static VOID output_begin_attribute(ent, aname, type)
  418. UNCH *ent, *aname;
  419. int type;
  420. {
  421.      flush_data();
  422.      if (ent)
  423.       printf("%c%s %s %s", DATA_ATTRIBUTE_CODE, ent, aname,
  424.          attribute_type_string(type));
  425.      else
  426.       printf("%c%s %s", ATTRIBUTE_CODE, aname,
  427.          attribute_type_string(type));
  428.  
  429. }
  430.  
  431. static VOID output_attribute_token(vallen, val)
  432. UNS vallen;
  433. UNCH *val;
  434. {
  435.      putchar(' ');
  436.      print_string(vallen, val, 0);
  437. }
  438.  
  439. static VOID output_end_attribute()
  440. {
  441.      putchar('\n');
  442. }
  443.  
  444. static VOID print_data(n, s, is_sdata)
  445. UNS n;
  446. UNCH *s;
  447. int is_sdata;
  448. {
  449.      if (n > 0) {
  450.       if (n == 1 && *s == RECHAR)
  451.            current_lineno++;
  452.       else
  453.            output_location();
  454.       if (!have_data)
  455.            putchar(DATA_CODE);
  456.       print_string(n, s, is_sdata);
  457.       have_data = 1;
  458.      }
  459. }
  460.  
  461. static VOID flush_data()
  462. {
  463.      if (have_data) {
  464.       putchar('\n');
  465.       have_data = 0;
  466.      }
  467. }
  468.  
  469. static VOID output_location()
  470. {
  471.      char *filename;
  472.      unsigned long lineno;
  473.      int filename_changed = 0;
  474.  
  475.      if (!locsw)
  476.       return;
  477.      if (!sgmlloc(&lineno, &filename))
  478.       return;
  479.      if (!current_filename || strcmp(filename, current_filename) != 0)
  480.       filename_changed = 1;
  481.      else if (lineno == current_lineno)
  482.       return;
  483.      flush_data();
  484.      printf("%c%lu", LOCATION_CODE, lineno);
  485.      current_lineno = lineno;
  486.      if (filename_changed) {
  487.       putchar(' ');
  488.       print_filename(filename);
  489.       current_filename = filename;
  490.      }
  491.      putchar('\n');
  492. }
  493.  
  494. static VOID print_string(slen, s, is_sdata)
  495. UNS slen;
  496. UNCH *s;
  497. int is_sdata;
  498. {
  499.      if (is_sdata)
  500.       fputs("\\|", stdout);
  501.      while (slen > 0) {
  502.       UNCH ch = *s++;
  503.       slen--;
  504.       if (ch == DELSDATA) {
  505.            if (is_sdata)
  506.             ;        /* I don't think this should happen */
  507.            else
  508.             fputs("\\|", stdout);
  509.            ;
  510.       }
  511.       else if (ch == DELCDATA)
  512.            ;
  513.       else {
  514.            if (ch == DELNONCH) {
  515.             if (!slen)
  516.              break;
  517.             ch = (*s++ - ADDNONCH) & 0xff;
  518.             slen--;
  519.            }
  520.            switch (ch) {
  521.            case DELCDATA:
  522.            case RSCHAR:
  523.             break;
  524.            case DELSDATA:
  525.             break;
  526.            case RECHAR:
  527.             fputs("\\n", stdout);
  528.             break;
  529.            case '\\':
  530.             fputs("\\\\", stdout);
  531.             break;
  532.            default:
  533.             if (ISASCII(ch) && isprint(ch))
  534.              putchar(ch);
  535.             else
  536.              printf("\\%03o", ch);
  537.             break;
  538.            }
  539.       }
  540.      }
  541.      if (is_sdata)
  542.       fputs("\\|", stdout);
  543. }
  544.             
  545.  
  546. static VOID print_id(id)
  547. UNIV id;
  548. {
  549.      char *p = id;
  550.  
  551.      if (!p || !*p)
  552.       return;
  553.      for (;;)  {
  554.       do {
  555.            switch (*p) {
  556.            case '\\':
  557.             fputs("\\\\", stdout);
  558.             break;
  559.            case '\n':
  560.             fputs("\\n", stdout);
  561.             break;
  562.            case ' ':
  563.             fputs("\\s", stdout);
  564.             break;
  565.            default:
  566.             if (ISASCII(*p) && isprint((UNCH)*p))
  567.              putchar(*p);
  568.             else
  569.              printf("\\%03o", (UNCH)*p);
  570.             break;
  571.            }
  572.       } while (*++p);
  573.       if (!*++p)
  574.            break;
  575.       putchar(' ');
  576.      }
  577. }
  578.  
  579. static VOID print_filename(s)
  580. char *s;
  581. {
  582.      for (; *s; s++)
  583.       switch (*s) {
  584.       case '\\':
  585.            fputs("\\\\", stdout);
  586.            break;
  587.       case '\n':
  588.            fputs("\\n", stdout);
  589.            break;
  590.       case ' ':
  591.            fputs("\\s", stdout);
  592.            break;
  593.       default:
  594.            if (ISASCII(*s) && isprint((UNCH)*s))
  595.             putchar(*s);
  596.            else
  597.             printf("\\%03o", (UNCH)*s);
  598.            break;
  599.       }
  600. }
  601.  
  602. /*
  603. Local Variables:
  604. c-indent-level: 5
  605. c-continued-statement-offset: 5
  606. c-brace-offset: -5
  607. c-argdecl-indent: 0
  608. c-label-offset: -5
  609. End:
  610. */
  611.